package com.wontube.client.extension.utils.net;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;

import com.wontube.client.extension.utils.net.RequestMethod;


/**
 * http connection
 * @author tanggf(2012-4-11)
 *
 */
public class HttpConnection {	
	private final String url;
	private HttpURLConnection conn = null;	
	private String charsetName = "UTF-8";
	private byte[] outputs = null;
	
	public HttpConnection(String url){		
		this.url = url;	
		this.init();
	}
	
	private void init(){
		try {
			this.conn = (HttpURLConnection) new URL(url).openConnection();
		} catch (Exception e) {
			this.conn = null;
			throw new RuntimeException(e);			
		}		
	}
	
	/**
	 * 是否使用缓存
	 * @param use
	 * @return
	 */
	public HttpConnection useCaches(boolean use){
		this.conn.setUseCaches(use);	
		return this;
	}
	
	/**
	 * 连接超时(millseconds)
	 * @param timeout
	 * @return
	 */
	public HttpConnection connectTimeout(int timeout){
		this.conn.setConnectTimeout(timeout);
		return this;
	}
	
	/**
	 * 读取超时
	 * @param timeout
	 * @return
	 */
	public HttpConnection readTimeout(int timeout){
		this.conn.setReadTimeout(timeout);
		return this;
	}
	
	/**
	 * connect/read timeout
	 * @param timeout
	 * @return
	 */
	public HttpConnection timeout(int timeout){
		this.conn.setConnectTimeout(timeout);
		this.conn.setReadTimeout(timeout);
		return this;
	}
	
	/**
	 * 请求方法
	 * @param method
	 * @return
	 */
	public HttpConnection methos(RequestMethod method){
		try {
			this.conn.setRequestMethod(method.toString());			
		} catch (ProtocolException e) {
			return this;
		}
		return this;
	}
	
	/**
	 * 是否需要发送请求数据
	 * @param dooutput
	 * @return
	 */
	public HttpConnection doOutput(boolean dooutput){
		this.conn.setDoOutput(dooutput);
		return this;
	}	
	
	/**
	 * 是否需要接收结果
	 * @param dooutput
	 * @return
	 */
	public HttpConnection doInput(boolean doinput){
		this.conn.setDoInput(doinput);
		return this;
	}
	
	/**
	 * 数据编码
	 * @param charsetName
	 * @return
	 */
	public HttpConnection charset(String charsetName){
		this.charsetName = charsetName;
		return this;
	}
	
	/**
	 * 请求数据(根据charset编码的字节数组)
	 * @param outputs
	 * @return
	 */
	public HttpConnection output(byte[] outputs){
		if(outputs != null && outputs.length > 0){
			this.conn.setDoOutput(true);
			this.outputs = outputs;
		}
		return this;
	}
	
	/**
	 * 是否跟随连接跳转3xx结果
	 * @param follow
	 * @return
	 */
	public HttpConnection followRedirect(boolean follow){
		this.conn.setInstanceFollowRedirects(follow);
		return this;
	}
	
	/**
	 * 设置请求头(如: Referer, Host, Cookie, User-Agent等)
	 * @param key
	 * @param value
	 * @return
	 */
	public HttpConnection header(String key, String value){
		this.conn.setRequestProperty(key, value);
		return this;
	}
	
	public HttpConnection referrer(String referrer){
		return header("Referer", referrer);		
	}
	
	public HttpConnection userAgent(String agent){
		return header("User-Agent", agent);
	}
	
	public HttpConnection cookie(String cookie){
		return header("Cookie", cookie);
	}
	
	/**
	 * 关闭连接, 如果使用getAsInputStream/Reader需要手工关闭
	 */
	public void close(){
		if(this.conn != null){
			this.conn.disconnect();
		}
	}
	
	public String getUrl(){
		return this.url;
	}
	
	/**
	 * 读取连接请求结果流
	 * @return
	 */
	public InputStream getAsInputStream(){
		if(this.conn == null){
			//重抛异常
			throw new RuntimeException("connection is null");
		}		
		try {
			this.conn.connect();
			if(this.outputs != null){
				OutputStream writer = conn.getOutputStream();
				try {					
					writer.write(this.outputs);
					writer.flush();
				} finally {
					writer.close();
				}				
			}
			return this.conn.getInputStream();
		} catch (Exception e) {
			//重抛异常
			throw new RuntimeException(e);
		} finally {
			this.conn.disconnect();
		}
	}
	
	/**
	 * 读取连接请求结果流
	 * @return
	 */
	public InputStreamReader getAsInputStreamReader(){
		InputStream stream = getAsInputStream();
		try {
			return new InputStreamReader(stream, this.charsetName);
		} catch (Exception e) {
			//重抛异常
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 读取结果流,并转化成字符串
	 * @return
	 */
	public String getAsString(){
		InputStreamReader reader = getAsInputStreamReader();	
		try {			
			StringBuilder sb = new StringBuilder();
			char[] cbuffer = new char[512];
			while (true) {
				int len = reader.read(cbuffer, 0, cbuffer.length);
				if (len <= 0) {
					break;
				}
				sb.append(cbuffer, 0, len);
			}

			return sb.toString();
		} catch (Exception e) {
			//重抛异常
			throw new RuntimeException(e);
		} finally {
			try {
				this.conn.disconnect();
				reader.close();
			} catch (IOException e) {				
				e.printStackTrace();
			}
		}
	}
}
